package com.leilei.controller;

import com.leilei.model.*;
import org.codehaus.jackson.map.ObjectMapper;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;


@ServerEndpoint("/service")
public class Game {
    public static ConcurrentLinkedQueue<Bullet> bullets=new ConcurrentLinkedQueue<Bullet>();
    public static ConcurrentLinkedQueue<Wall> walls=new ConcurrentLinkedQueue<Wall>();
    public static BlockingQueue<Effect> effects=new ArrayBlockingQueue<>(50);
    public static ConcurrentLinkedQueue<SafePlace> HealthPlaces=new ConcurrentLinkedQueue<>();
    public static ConcurrentLinkedQueue<SafePlace> PowerPlaces=new ConcurrentLinkedQueue<>();
    public static ConcurrentLinkedQueue<String> names=new ConcurrentLinkedQueue<>();
    public static Map<String ,Player> map=new ConcurrentHashMap<String, Player>();
    public static ConcurrentLinkedQueue<ConcurrentLinkedQueue<Effect>> allUsersEffects=new ConcurrentLinkedQueue<>();
    static {
        HealthPlaces.add(new SafePlace());
        HealthPlaces.add(new SafePlace());
        PowerPlaces.add(new SafePlace());
        PowerPlaces.add(new SafePlace());
        PowerPlaces.add(new SafePlace());
        new Thread(()->{
            while (true){
                try {
                    Effect take = effects.take();
                    allUsersEffects.forEach(e->{
                        try {
                            e.add(take);
                        } catch (Exception e1) {
                            e1.printStackTrace();
                        }
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
    private ObjectMapper objectMapper=new ObjectMapper();
    private Session session;
    private Player player;
    private MyBigBullet myBigBullet=new MyBigBullet();
    private ConcurrentLinkedQueue<Effect> myEffects=new ConcurrentLinkedQueue<Effect>();
    private long lastTime=new Date().getTime();
    @OnOpen
    public void Open(Session session){
        System.out.println("有人连接");
        this.session=session;
        allUsersEffects.add(myEffects);
    }
    @OnMessage
    public void Msg(String msg) throws IOException {
        PowerAdd();
        GameRun(msg);
    }
    @OnClose
    public void Close(){
        System.out.println("有人断线");
        if (map.containsKey(session.getId())){
            map.remove(this.session.getId());
            allUsersEffects.remove(myEffects);
        }
        if(names.contains(player.getId()))
            names.remove(player.getId());
    }

    @OnError
    public void error(Throwable throwable){
        throwable.printStackTrace();
    }

    public void GameRun(String msg) throws IOException {
        String code=msg.substring(0,1);
        switch (code) {
            case "1":
                player=Play.PlayerFight(objectMapper.readValue(msg.substring(1),Player.class),myBigBullet);
                player.setMyBigBullet(myBigBullet);
                if(!map.containsKey(session.getId())){
                    if(names.contains(player.getId())){
                        session.close();
                        break;
                    }
                    names.add(player.getId());
                }
                map.put(session.getId(),player);
                sendMsg(Play.GetData(myEffects));
                break;
            case "2":
                Bullet bullet = objectMapper.readValue(msg.substring(1), Bullet.class);
                bullet.setPlayer(myBigBullet);
                bullets.add(bullet);
                Play.bulletGo(bullet);
                break;
            case "3":
                if (myBigBullet.getPower().get()>=10&&myBigBullet.getMyWall()==null){
                    myBigBullet.setMyWall(objectMapper.readValue(msg.substring(1), Wall.class));
                    myBigBullet.getMyWall().setPlayer(myBigBullet);
                    walls.add(myBigBullet.getMyWall());
                    myBigBullet.getPower().addAndGet(-10);
                    myBigBullet.setGrow(true);
                    Play.WallGrow(player,myBigBullet);
                }
                break;
            case "4":
                if (myBigBullet.getMyWall()!=null){
                    myBigBullet.setGrow(false);
                    myBigBullet.setMyWall(null);
                }
                break;
            case "5":
                if (myBigBullet.isGrow()&&myBigBullet.getMyWall()!=null)
                    myBigBullet.getMyWall().setFace(Double.parseDouble(msg.substring(1)));
                break;
        }
    }



    private void sendMsg(String msg){
        try {
            session.getBasicRemote().sendText(msg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void PowerAdd(){
        long now=new Date().getTime();
        if (player!=null&&(myBigBullet.getPower().get()<100)||myBigBullet.getHealth().get()<10){
            long time=300;
            while (now-lastTime>time){
                if(myBigBullet.getPower().get()<100){
                    myBigBullet.getPower().incrementAndGet();
                }
                Play.RecoveryHealth(player,myBigBullet);
                Play.RecoveryPower(player,myBigBullet);
                lastTime+=time;
            }
        }else {
            lastTime=now;
        }
    }
}